

#include <string.h>
#include <stdlib.h>

/***********************************************************************************/

#define size_of_ptr   sizeof(void*)
#define sizeof_cache (sizeof(size_t) * 8192)
#define size_of_min(a, b) ((a) < (b) ? (a) : (b))

/***********************************************************************************/

class mallotor final {
public:
  inline mallotor()
    : ri(0), wi(0) {
    memset(mp, 0, sizeof(mp));
  }

  inline ~mallotor() {
    while (wi - ri) ::free(pop());
  }

  void* pop() {
    void* p = nullptr;
    size_t n = size_of_min(size_of_ptr, wi - ri);
    if (n) {
      size_t i = (ri & (sizeof_cache - 1));
      *(size_t*)(&p) = *(size_t*)(mp + i);
      ri += n;
    }
    return p;
  }

  bool push(void* p) {
    size_t n = size_of_min(size_of_ptr, sizeof_cache - (wi - ri));
    if (n) {
      size_t i = (wi & (sizeof_cache - 1));
      *(size_t*)(mp + i) = (size_t)p;
      wi += n;
    }
    return n == size_of_ptr;
  }

private:
  size_t ri, wi;
  char mp[sizeof_cache];
};

/***********************************************************************************/

static thread_local mallotor allotor;

/***********************************************************************************/

void* local_new(size_t size) {
  void* mem = allotor.pop();
  return mem ? mem : ::malloc(size);
}

/***********************************************************************************/

void local_delete(void* ptr) {
  if (ptr && allotor.push(ptr) == false) {
    ::free(ptr);
  }
}

/***********************************************************************************/
